home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Gold Medal Software 2
/
Gold Medal Software Volume 2 (Gold Medal) (1994).iso
/
graphics
/
plotter.arj
/
PLOTTER.C
< prev
next >
Wrap
Text File
|
1993-08-06
|
18KB
|
635 lines
/* PLOTTER.C */
#include <conio.h>
#include <ctype.h>
#include <dos.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <graphics.h>
#include <math.h>
#define LEFT -75
#define RIGHT -77
#define MAX(x,y) (x)>(y) ? x : y
#define MIN(x,y) (x)<(y) ? x : y
/* for dimensioning horizons, assume VGA max */
#define HSCREEN 640
#define VSCREEN 480
/* upper bound on x- and z-divisions */
#define MAXDIV 101
int numX, numZ;
float X[MAXDIV], Z[MAXDIV];
float Y[MAXDIV][MAXDIV]; /* Y[j][i] = f(X[i],Z[j]) */
int theta0, alpha0; /* rotation angles, degrees */
float theta, alpha; /* rotation angles, radians */
int left, top, right, pbot; /* plot window limits */
char filename[30]; /* data file */
int loaded = 0; /* 'function loaded' flag */
int sxmax, symax; /* maximum,minimum screen coordinates */
int start, end; /* cursor start and end lines */
char title[80]; /* function name (formula, etc. */
float xpmin, xpmax, ypmin, ypmax; /* extreme transformed screen values */
int eflag; /* if set, use exact max/min in scale() */
char *item[] = {" Load File ", " Viewpoint ", " Plot ", " Quit "};
int len[4], pos[4], th0, tw0, mtop, mbot, ttop, tbot;
int v[8]; /* for drawing windows */
int border = 7, bgrnd = 6; /* menu color values */
int height[] = {40, 40}; /* menu heights */
int width[] = {300, 144}; /* and widths */
int a0, b0, c0, d0, a1, b1, c1, d1; /* menu corners */
int current; /* menu current option */
void *buffer; /* for saving screen under windows */
/* function prototypes */
int
coeff(float v, float w, float v0, float w0, double *c1, double *c2),
get_angles(),
get_file(),
getint(int n, char *s, int vi[]),
getkey(void),
getstr(char *s, int len),
init_graphics(),
normal_exit(void),
scale();
extern int setup_xform(float, float); /* defined in hlplot.c */
/* varibles and arrays defined in hlplot.c */
extern int Upper[HSCREEN],Lower[HSCREEN]; /* horizon arrays used in hlplot */
extern int Xleft,Xright,Yleft,Yright; /* used in hlplot to track edges */
extern double ax, bx, ay, by; /* scaling constants */
extern double a00, a01, a11, a20, a21; /* entries in transformation matrix */
main()
{
unsigned size1, size2, size;
int ltr[] = {'l', 'v', 'p', 'q'};
int i, c, selection;
get_cursor(&start, &end); /* save cursor shape */
init_graphics(); /* initialize graphics for later use */
barmenu(0);
top = mbot + 3;
left = 0;
right = sxmax, pbot = symax - 48;
ttop = pbot + 1;
tbot = symax;
a0 = pos[0];
b0 = mbot + 4;
c0 = a0 + width[0];
d0 = b0 + height[0];
a1 = pos[1];
b1 = mbot + 4;
c1 = a1 + width[1];
d1 = b1 + height[1];
size1 = imagesize(a0, b0, c0, d0);
size2 = imagesize(a1, b1, c1, d1);
size = size1 > size2 ? size1 : size2;
if ((buffer = malloc(size)) == NULL) {
closegraph();
printf("Not enough memory for buffer\n");
exit(1);
}
/* frame plot area and text area */
setcolor(15);
rectangle(left, top, right, pbot);
fill_text_area(7);
/* get initial file */
if (get_file()) {
norm(current);
loaded = 1;
fill_text_area(7);
put_text(); /* print title, etc. */
current = 2; /* return to 'Plot' */
high(current);
} else
putimage(a0, b0, buffer, COPY_PUT); /* restore screen under window */
while (1) {
selection = -1;
switch (c = getkey()) {
case RIGHT:
norm(current);
if (current == 3)
current = 0;
else
current++;
high(current);
break;
case LEFT:
norm(current);
if (current == 0)
current = 3;
else
current--;
high(current);
break;
case 13: /* make selection when Enter key pressed */
selection = current;
break;
case 27: /* Esc is alternate exit key */
normal_exit();
default: /* if letter command, change highlight and
* select */
for (i = 0; i < 4; i++)
if (ltr[i] == c || ltr[i] - 32 == c) {
norm(current);
current = i;
high(current);
selection = current;
break;
}
}
if (selection >= 0) {
switch (selection) {
case 0: /* Load File */
if (get_file()) {
norm(current);
loaded = 1;
fill_text_area(7);
put_text(); /* print title, etc. */
current = 2; /* return to 'Plot' */
high(current);
break;
} else {
putimage(a0, b0, buffer, COPY_PUT); /* restore screen under
* window */
}
break;
case 1: /* 'Viewpoint' */
norm(current);
if (get_angles()) {
fill_text_area(7);
put_text(); /* to upgrade angle display */
current = 2; /* return to 'Plot' */
} else
putimage(a1, b1, buffer, COPY_PUT);
high(current);
break;
case 2: /* 'Plot' */
norm(2);
scale();
plot();
current = 1; /* return to 'Viewpoint' */
high(current);
break;
case 3: /* 'Quit' */
normal_exit();
}
}
}
}
/* ============== alphabetical listing of demo functions ================= */
barmenu()
{ /* setup menu bar */
int i, lentotal = 0;
settextstyle(1, 0, 1); /* triplex font for menu text */
tw0 = textwidth("H");
th0 = textheight("H");
mtop = 0;
mbot = th0 + 6;
for (i = 0; i < 4; i++) {
len[i] = textwidth(item[i]) + 4 * tw0;
lentotal += len[i];
}
pos[0] = (sxmax - lentotal) / 2; /* center menu items */
pos[1] = pos[0] + len[0]; /* starting x-values for items 0-3 */
pos[2] = pos[1] + len[1];
pos[3] = pos[2] + len[2];
setcolor(15); /* bright white border */
setfillstyle(1, 7); /* dull white interior */
bar3d(pos[0] - 2 * tw0, mtop, pos[3] + 6 * tw0, mbot, 0, 0);
setcolor(0); /* normal text color = black */
high(0);
norm(1);
norm(2);
norm(3);
}
/* set scaling coefficients c1,c2 so that c1*v +c2 = v0 and c1*w + c2 = w0 */
coeff(float v, float w, float v0, float w0, double *c1, double *c2)
{
*c1 = (double) (w0 - v0) / (w - v);
*c2 = (double) (v0 - (*c1) * v);
}
/*---------------------------------------------------------------------------*/
/* Routine to center a string 'inside itself' */
center(char *s)
{
int i,n,k,ls,ts,ns;
char s1[81];
n = strlen(s);
if (n > 80)
return 0;
i = 0;
while(s[i] == ' ')
i++;
ls = i;
i = n-1;
while(s[i] == ' ')
i--;
ts = n-i-1;
ns = n - (ls+ts);
k = (ls+ts)/2;
for (i=0; i<k; i++)
s1[i] = ' ';
for (i=0; i<ns; i++)
s1[k+i] = s[ls+i];
for (i=k+ns; i<n; i++)
s1[i] = ' ';
s1[n] = '\0';
strcpy(s,s1);
return 1;
}
/*---------------------------------------------------------------------------*/
fill_text_area(int color)
{
setfillstyle(SOLID_FILL, color);
v[0] = v[6] = v[8] = 0;
v[1] = v[3] = v[9] = ttop;
v[2] = v[4] = sxmax;
v[5] = v[7] = symax;
fillpoly(5, v);
}
/*---------------------------------------------------------------------------*/
get_angles()
{
char s[12];
int vi[2]; /* for input of theta and alpha */
int c;
settextstyle(0, 0, 1);
getimage(a1, b1, c1, d1, buffer);
gwindow(a1 + 1, b1 + 1, c1 - 1, d1 - 1, bgrnd, border);
setcolor(15);
if (!loaded) {
outtextxy(a1 + 8, b1 + 11, "No file loaded");
outtextxy(a1 + 8, b1 + 24, "Press any key");
getch();
return 0;
}
outtextxy(a1 + 8, b1 + 10, "Angle THETA: ");
c = getgstr(a1 + 112, b1 + 10, s);
if (c == -1) /* escape pressed */
return 0;
if (c == 0) { /* empty entry */
gprintf(a1 + 112, b1 + 10, 15, "%d", theta0);
goto a0;
}
if (!s[0])
return 0;
theta0 = atoi(s);
a0:
outtextxy(a1 + 8, b1 + 24, "Angle ALPHA: ");
c = getgstr(a1 + 112, b1 + 24, s);
if (c == -1)
return 0;
if (c == 0) {
gprintf(a1 + 112, b1 + 24, 15, "%d", alpha0);
goto a1;
}
if (!s[0])
return 0;
alpha0 = atoi(s);
a1:
/* adjust sizes if necessary */
theta0 = theta0 < -45 ? -45 : theta0 > 45 ? 45 : theta0;
alpha0 = alpha0 < -45 ? -45 : alpha0 > 45 ? 45 : alpha0;
putimage(a1, b1, buffer, COPY_PUT);
return 1;
}
/* --------------------------------------------------------------------- */
get_cursor(int *start, int *end)
{
_AH = 3;
_BH = 0;
geninterrupt(0x10);
*start = _CH;
*end = _CL;
}
/* --------------------------------------------------------------------- */
get_file()
{
int i, j, c;
char *p, s[1];
FILE *fp;
getimage(a0, b0, c0, d0, buffer);
gwindow(a0 + 1, b0 + 1, c0 - 1, d0 - 1, bgrnd, border);
setcolor(15);
outtextxy(a0 + 8, b0 + 5, "File : ");
if (getgstr(a0 + 64, b0 + 5, filename) <= 0)
return 0;
eflag = 0;
if ((p = strchr(filename, '/')) != NULL) {
eflag = 4;
*p = '\0';
}
fp = fopen(filename, "r+b");
if (fp == NULL) {
outtextxy(a0 + 8, b0 + 24, "File not found; Press any key.");
getch();
return 0;
}
strupr(filename);
outtextxy(a0 + 8, b0 + 25, "Reading file ...");
if (strstr(filename, ".ASC"))
read_asc_data(fp);
else
read_bin_data(fp);
fclose(fp);
theta0 = theta0 < -45 ? -45 : theta0 > 45 ? 45 : theta0;
alpha0 = alpha0 < -45 ? -45 : alpha0 > 45 ? 45 : alpha0;
putimage(a0, b0, buffer, COPY_PUT); /* restore screen under window */
return 1;
}
/*-------------------------------------------*/
read_bin_data(FILE *fp)
{
int j;
fread(title, sizeof(char), 70, fp);
title[70] = '\0';
center(title);
fread(&numX, sizeof(int), 1, fp);
fread(&numZ, sizeof(int), 1, fp);
fread(X, sizeof(float), numX, fp);
fread(Z, sizeof(float), numZ, fp);
for (j = 0; j < numZ; j++)
fread(&Y[j], sizeof(float), numX, fp);
fread(&theta0, sizeof(int), 1, fp);
fread(&alpha0, sizeof(int), 1, fp);
}
/*-------------------------------------------*/
read_asc_data(FILE *fp)
{
int i,j;
fread(title, sizeof(char), 70, fp);
title[70] = '\0';
center(title);
fscanf(fp, "%d %d", &numX, &numZ);
for (i = 0; i < numX; i++)
fscanf(fp, "%f", &X[i]);
for (j = 0; j < numZ; j++)
fscanf(fp, "%f", &Z[j]);
for (j = 0; j < numX; j++)
for (i = 0; i < numX; i++)
fscanf(fp, "%f", &Y[j][i]);
theta0 = alpha0 = 0;
if (!feof(fp))
fscanf(fp, "%d %d", &theta0, &alpha0);
}
/*---------------------------------------------------------------------------*/
/* extract n integer values from string s, put them in array vi[] */
getint(int n, char *s, int vi[])
{
int cnt = 0;
char *p;
if (n == 0)
return cnt;
p = s;
while (cnt < n && *p) {
while (!isdigit(*p) && *p != '-')
p++;
vi[cnt] = atoi(p);
p++;
while (isdigit(*p))
p++;
cnt++;
}
return cnt;
}
/*---------------------------------------------------------------------------*/
/* basic input loop feeder */
getkey(void)
{
int k;
k = getch();
if (k == 0)
k = -getch();
return k;
}
/* --------------------------------------------------------------------- */
/* get user input (into array t[]), echo on screen at (x1,y1) */
/* eol stops input; backspace ok, no other editing functions implemented */
/* for graphics modes only */
int
getgstr(int x1, int y1, char *t)
{
int x0 = x1, width = 8;
char *p, c, s1[2];
p = t;
s1[1] = '\0';
moveto(x1, y1);
while ((c = getch()) != '\r') {
if (c == 27) /* leave if Esc pressed */
return -1; /* to indicate abnormal exit */
if (isprint(c) && x1 < sxmax - width) {
s1[0] = c;
outtext(s1);
x1 = getx();
*p = c;
p++;
}
if (c == 8 && x1 > x0) {
x1 -= width;
p--;
moveto(x1, y1);
bar(x1, y1, x1 + width, y1 + width);
}
}
*p = '\0';
if (p == t)
return 0; /* no input */
return 1; /* normal exit */
}
/* ---------------------------------------------------------------------- */
/* graphics version of printf(); from Borland graphics demo BGIDEMO.C */
/* prints string at pixel location (x,y) in color c */
gprintf(int x, int y, int c, char *fmt,...)
{
va_list argptr;
char str[140];
va_start(argptr, fmt);
vsprintf(str, fmt, argptr);
setcolor(c);
outtextxy(x, y, str);
va_end(argptr);
}
/* ---------------------- Set up graphics window ------------------------- */
gwindow(x0, y0, z0, w0, bgrnd, border)
int x0, y0; /* upper left corner */
int z0, w0; /* lower right corner */
int bgrnd, border; /* colors */
{
int i;
setcolor(border);
setlinestyle(SOLID_LINE, 0, THICK_WIDTH); /* for borders of windows */
setfillstyle(SOLID_FILL, bgrnd);
v[0] = v[6] = v[8] = x0;
v[1] = v[3] = v[9] = y0;
v[2] = v[4] = z0;
v[5] = v[7] = w0;
fillpoly(5, v);
setlinestyle(SOLID_LINE, 0, NORM_WIDTH);
}
/*------------------------- part of menu system ---------------------------- */
high(int i)
{
settextstyle(1, 0, 1); /* triplex font for menu text */
setcolor(12);
outtextxy(pos[i], mtop + 1, item[i]);
settextstyle(0, 0, 1); /* reset normal text */
}
/*---------------------------------------------------------------------------*/
init_graphics()
{
int graphdriver = DETECT, graphmode;
char *pathtodriver = "c:\\tbc";
registerbgifont(triplex_font);/* assuming in graphics.lib */
initgraph(&graphdriver, &graphmode, pathtodriver);
if (graphdriver != EGA && graphdriver != VGA) {
printf("This program requires EGA or VGA graphics.");
exit(1);
}
sxmax = getmaxx();
symax = getmaxy();
}
/*------------------------- part of menu system ---------------------------- */
norm(int i)
{
settextstyle(1, 0, 1); /* triplex font for menu text */
setcolor(0);
outtextxy(pos[i], mtop + 1, item[i]);
settextstyle(0, 0, 1); /* reset normal text */
}
/*---------------------------------------------------------------------------*/
normal_exit(void)
{
closegraph();
exit(0);
}
/* ------------------------------------------------------------------------- */
put_text()
{
char s[80], view[22];
int tw;
sprintf(s, " %s Xdiv: %d, Zdiv: %d", filename, numX, numZ);
sprintf(view, "View angles: %d,%d", theta0, alpha0);
setcolor(0); /* black graphics text */
if (strlen(title))
outtextxy(12, ttop + 12, title); /* print title */
outtextxy(4, ttop + 30, s); /* print filename, divisions */
tw = textwidth(view) + 4 * tw0;
outtextxy(right - tw, ttop + 30, view); /* print view angles */
}
/* ---------------- initialize scaling constants, etc. ----------------------*/
scale()
{
double deg2rad;
float x, y, z, x1, y1;
float t;
int i, j, deltaX, deltaZ;
deg2rad = atan(1) / 45;
/* change angles from degrees to radians: */
theta = theta0 * deg2rad;
alpha = alpha0 * deg2rad;
/* initialize various constants: */
setup_xform(theta, alpha);
Xleft = Yleft = Xright = Yright = -1;
/* initialize horizon arrays */
for (i = 0; i < sxmax; i++) {
Upper[i] = 0;
Lower[i] = symax;
}
/* find (approx) maximum and minimum x,y for the projection */
/* use deltaX and detaZ to limit number of xz-values checked */
xpmin = ypmin = 1e10;
xpmax = ypmax = -1e10;
if ((numX - 1) % 5 || (numZ - 1) % 5)
eflag = 4; /* don't approximate in this case */
deltaX = deltaZ = 5 - eflag; /* eflag = 0 or 4; if set, check all levels */
for (j = 0; j < numZ; j += deltaZ) {
z = Z[j];
for (i = 0; i < numX; i += deltaX) {
x = X[i];
y = Y[j][i];
x1 = a00 * x + a20 * z;
y1 = a01 * x + a11 * y + a21 * z;
if (x1 < xpmin)
xpmin = x1;
if (x1 > xpmax)
xpmax = x1;
if (y1 < ypmin)
ypmin = y1;
if (y1 > ypmax)
ypmax = y1;
}
}
/* set scaling constants so that graph fills viewport */
coeff(xpmin, xpmax, left + 15.0, right - 15.0, &ax, &bx);
coeff(ypmin, ypmax, pbot - 15.0, top + 15.0, &ay, &by);
}
/*---------------------------------------------------------------------------*/
showcursor()
{
_AX = 0x0100;
_BX = 0;
_CH = (unsigned) start; /* start, end = original values */
_CL = (unsigned) end;
geninterrupt(0x10);
}